/*
 * Copyright 2011 J. Auer, J. Andert, F.-J. Jendrusch, U. Celebi
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package de.fuberlin.replication.application.android;

import java.util.concurrent.Semaphore;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;

/**
 * Abstract rotation callback implementation.
 */
public abstract class RotatableAbstract implements Rotatable {
	private Activity activity;

	/** User interface handler. */
	Handler handler;

	@Override
	public synchronized Activity getActivity() {
		while (activity == null)
			try {
				wait();
			} catch (InterruptedException e) {
				continue;
			}

		return activity;
	}

	@Override
	public synchronized void setActivity(Activity activity) {
		this.activity = activity;

		if (activity != null)
			notifyAll();
	}

	/**
	 * Synchronously runs the given action on the ui thread.
	 * 
	 * @param action the action to be run.
	 * @see Activity#runOnUiThread(Runnable)
	 */
	public void syncRunOnUiThread(final Runnable action) {
		final Semaphore wait = new Semaphore(0);

		Runnable enclosingAction = new Runnable() {
			@Override
			public void run() {
				try {
					action.run();
				} finally {
					wait.release();
				}
			}
		};

		getActivity().runOnUiThread(enclosingAction);

		wait.acquireUninterruptibly();
	}

	/**
	 * Returns the user interface handler.
	 * 
	 * @return the user interface handler.
	 */
	public Handler getUIHandler() {
		if (handler == null)
			syncRunOnUiThread(new Runnable() {
				@Override
				public void run() {
					handler = new Handler(new UICallback());
				}
			});

		return handler;
	}

	/**
	 * User interface handler callback.
	 */
	public class UICallback implements Handler.Callback {
		/** @see Activity#showDialog(int, Bundle) */
		public static final int MESSAGE_DIALOG_SHOW = 1;

		/** @see Activity#dismissDialog(int) */
		public static final int MESSAGE_DIALOG_DISMISS = 2;

		/** @see Activity#removeDialog(int) */
		public static final int MESSAGE_DIALOG_REMOVE = 3;

		/** @see Toast#makeText(android.content.Context, int, int) */
		public static final int MESSAGE_TOAST = 4;

		@Override
		public boolean handleMessage(Message msg) {
			switch (msg.what) {
				case MESSAGE_DIALOG_SHOW:
					getActivity().showDialog(msg.arg1, (Bundle) msg.obj);

					break;
				case MESSAGE_DIALOG_DISMISS:
					getActivity().dismissDialog(msg.arg1);

					break;
				case MESSAGE_DIALOG_REMOVE:
					getActivity().removeDialog(msg.arg1);

					break;
				case MESSAGE_TOAST:
					Toast.makeText(getActivity(), msg.arg1, msg.arg2).show();

					break;
				default:
					return false;
			}

			return true;
		}
	}
}